Skip to content

Fix source code not displaying for implicit and deterministic accounts#4

Open
r-near wants to merge 1 commit intoSourceScan:mainfrom
r-near:fix/support-implicit-deterministic-accounts
Open

Fix source code not displaying for implicit and deterministic accounts#4
r-near wants to merge 1 commit intoSourceScan:mainfrom
r-near:fix/support-implicit-deterministic-accounts

Conversation

@r-near
Copy link

@r-near r-near commented Mar 12, 2026

Summary

  • The TLD validation in the /contract/[slug] and /code/[slug] pages rejects any account ID that doesn't end with .near or .testnet, which blocks all implicit and deterministic account types from ever reaching the data-fetching code path
  • Verified that the on-chain data does exist for these accounts (e.g. 0sa8247564c6774a33b975a053fc4fbebbd869772d returns CID, code hash, lang from get_contract), and the IPFS source files are accessible — the frontend just refuses to show them
  • Replaced the strict .near/.testnet suffix check with isValidNearAccount() which recognizes all four NEAR account types from near-account-id 2.0: named accounts, NEAR implicit (64-char hex), ETH implicit (0x + 40 hex), and deterministic (0s + 40 hex)

Context

Reported in this Slack thread — a user verified a global deployer contract at a deterministic account ID but the source code isn't visible on SourceScan.

Test plan

  • isValidNearAccount accepts 0s + 40 hex (deterministic), 0x + 40 hex (ETH implicit), 64-char hex (NEAR implicit), .near, .testnet
  • isValidNearAccount rejects garbage strings, short hex, uppercase hex, empty strings
  • Queried get_contract for 0sa8247564c6774a33b975a053fc4fbebbd869772d via local proxy → returns valid CID/code_hash/lang
  • IPFS structure endpoint returns source files for the returned CID
  • /contract/0sa824... and /code/0sa824... pages proceed to loading state instead of showing "Invalid contract address"
  • next build succeeds, next lint has no new warnings

The TLD validation gate rejected any account ID not ending in .near or
.testnet, which blocked NEAR implicit (64-char hex), ETH implicit (0x),
and deterministic (0s) accounts from ever reaching the data-fetching
code path. Verification data exists on-chain for these accounts but the
frontend refused to display it.

Replace the strict TLD check with isValidNearAccount() which recognises
all four NEAR account types defined in near-account-id 2.0.
Copilot AI review requested due to automatic review settings March 12, 2026 20:58
@vercel
Copy link
Contributor

vercel bot commented Mar 12, 2026

@r-near is attempting to deploy a commit to the 2BeBuilt Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes SourceScan’s /contract/[slug] and /code/[slug] pages rejecting implicit and deterministic NEAR account IDs during upfront validation, allowing those accounts to reach the normal data-fetching/rendering path.

Changes:

  • Added implicit/deterministic account pattern detection and broadened address validation to accept those formats.
  • Updated /contract/[slug] and /code/[slug] pages to use the new validation helper and improved the user-facing invalid-address message.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
utils/detectNetwork.ts Introduces implicit/deterministic account detection and replaces TLD-only validation with isValidNearAccount.
pages/contract/[slug].tsx Swaps .near/.testnet suffix checks for isValidNearAccount and updates invalid-address UI text.
pages/code/[slug].tsx Swaps .near/.testnet suffix checks for isValidNearAccount in two effects and updates invalid-address messages/UI text.
Comments suppressed due to low confidence (1)

pages/code/[slug].tsx:459

  • The Code page now has two separate effects that both validate accountId and perform network detection/switching (one near the top of the component and this one). This duplication makes it easy for behavior to drift (e.g., one effect updated without the other). Consider consolidating validation + network detection into a single effect and deriving invalidTLD/error state from that result.
  useEffect(() => {
    if (accountId) {
      if (!isValidNearAccount(accountId)) {
        console.log(`Code page: Invalid account ID: ${accountId}`)
        setLoading(false)
        setErrorMessage(
          `Invalid contract address: ${accountId}. Must be a named account (.near/.testnet) or an implicit/deterministic account.`
        )
        setInvalidTLD(true)
        return
      }

      const detectedNetwork = detectNetworkFromAddress(accountId)
      if (detectedNetwork && detectedNetwork !== network) {
        console.log(
          `Code page: Detected ${detectedNetwork} contract, switching networks from ${network}`
        )
        setNetwork(detectedNetwork)
      } else {
        // If no network switch needed, mark detection as complete
        setNetworkDetected(true)
      }
    }
  }, [accountId]) // Only depend on accountId to avoid re-running when network changes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to 34
/**
* Detects the network type from a contract address based on its TLD.
* Returns null for implicit/deterministic accounts since they can exist on either network.
*/
export const detectNetworkFromAddress = (
contractAddress: string
): NetworkType | null => {
if (!contractAddress) return null

// Check if the address ends with .near (mainnet) or .testnet (testnet)
if (contractAddress.endsWith('.near')) {
return 'mainnet'
} else if (contractAddress.endsWith('.testnet')) {
return 'testnet'
}

// If no specific TLD is found, return null
// Implicit and deterministic accounts can exist on either network
return null
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detectNetworkFromAddress doc says it “Returns null for implicit/deterministic accounts”, but the function also returns null for any non-.near/.testnet named account (e.g. top-level accounts) and for invalid strings. Consider updating the comment to reflect the actual behavior (null when the network can't be inferred from a known suffix).

Copilot uses AI. Check for mistakes.
Comment on lines 37 to 47
/**
* Checks if a contract address has a valid NEAR TLD (.near or .testnet)
* @param contractAddress The contract address to check
* @returns Boolean indicating if the address has a valid TLD
* Checks if a contract address is a valid NEAR account identifier.
* Accepts named accounts (.near/.testnet) and implicit/deterministic accounts.
*/
export const hasValidTLD = (contractAddress: string): boolean => {
export const isValidNearAccount = (contractAddress: string): boolean => {
if (!contractAddress) return false
return (
contractAddress.endsWith('.near') || contractAddress.endsWith('.testnet')
contractAddress.endsWith('.near') ||
contractAddress.endsWith('.testnet') ||
isImplicitAccount(contractAddress)
)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isValidNearAccount is documented/named as a full NEAR account identifier validator, but the implementation only checks for .near/.testnet suffixes or implicit/deterministic patterns (so many invalid “*.near” strings would pass, and valid top-level named accounts would fail). Either tighten the validation to match the NEAR account-id rules (or use a dedicated validator lib) or rename/adjust the docstring to reflect that this is a “supported address format” check rather than full validation.

Copilot uses AI. Check for mistakes.
Comment on lines +251 to 255
if (!isValidNearAccount(accountId)) {
console.log(`Invalid account ID: ${accountId}`)
setLoading(false)
setInvalidTLD(true)
return
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The state name invalidTLD is now misleading because the check was broadened beyond TLDs (it now validates implicit/deterministic formats too). Consider renaming this state (and related UI copy/console message) to something like invalidAccountId to avoid confusion in future changes.

Copilot uses AI. Check for mistakes.
Comment on lines 435 to 445
// Update the TLD validation to set the invalidTLD state
useEffect(() => {
if (accountId) {
// Check if the TLD is valid (.near or .testnet)
const isValidTLD =
accountId.endsWith('.near') || accountId.endsWith('.testnet')
if (!isValidTLD) {
console.log(`Code page: Invalid TLD for contract: ${accountId}`)
if (!isValidNearAccount(accountId)) {
console.log(`Code page: Invalid account ID: ${accountId}`)
setLoading(false)
setErrorMessage(
`Invalid contract address: ${accountId}. Contract addresses must end with .near or .testnet`
`Invalid contract address: ${accountId}. Must be a named account (.near/.testnet) or an implicit/deterministic account.`
)
setInvalidTLD(true)
return
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this effect, the variable/comment naming still refers to “TLD” (invalidTLD, “TLD validation”), but the logic now validates the full account ID format (named vs implicit/deterministic). Renaming the state/comment would make the intent clearer and prevent confusion when extending validation further.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to 47
export const isValidNearAccount = (contractAddress: string): boolean => {
if (!contractAddress) return false
return (
contractAddress.endsWith('.near') || contractAddress.endsWith('.testnet')
contractAddress.endsWith('.near') ||
contractAddress.endsWith('.testnet') ||
isImplicitAccount(contractAddress)
)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says isValidNearAccount() “recognizes all four NEAR account types from near-account-id 2.0”, but the implementation here is a custom suffix/regex check and does not implement full NEAR named-account validation rules (nor use the near-account-id package). Either update the PR description to match what’s implemented, or switch the implementation to use the intended library/validation semantics.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants